import EventDispatcher from "../../event/EventDispatcher";
import Service from "../service/Service";
import TSMap from "../../math/TSMap";
import ServiceBuilder from "../service/ServiceBuilder";
import NetConfig from "../NetConfig";
import ServiceInterface from "../service/ServiceInterface";
import MessageHandler from "../handler/MessageHandler";
import ReceiveMessage from "../message/ReceiveMessage";
import SendMessage from "../message/SendMessage";
import ServiceInfo from "../service/ServiceInfo";

/**
 * 发送失败应该再代理这边处理。
 */
export default abstract class RemoteProxy  extends EventDispatcher implements  ServiceInterface{


    protected serviceInfo:ServiceInfo;

    protected service:Service;

    protected msgHandler:MessageHandler;


    // 连接次数
    protected connectCount: number = 0;

    protected connectTimeID ;

    // 是否是主动断开的。
    private isActiveClose:boolean = false;
     // 最大发送次数
 
     /**
      * 不同的服务可以使用相同的协议号
      * 发送数据后的缓存，同时只能发送一个相同的消息。
      */
    protected  msgMap:TSMap = new TSMap();  
    

    constructor(msgHandler:MessageHandler){
        super();
        this.msgHandler = msgHandler; 
    }

    getState(){
        if(this.service){
            return this.service.getState();
        }
        return NetConfig.CLOSED;
    }




    getCloseFlag(){
        return this.isActiveClose;
    }


    

    isReady(){
        // cc.log(' this.service.isReady() ',this.service.isReady())
        return this.service != null && this.service.isReady();
    }



    /**
     * 发送协议和返回协议映射表
     * @param map 
     */
    connect(sInfo:ServiceInfo){
        this.serviceInfo = sInfo;
        this.msgHandler.init();
        this.connectCount = 0;
        this.msgMap.clear();
        // cc.log("RemoteProxy connectType "+this.messageType+" ip "+this.serviceID);
        this.destroy();
        this.isActiveClose = false;
        if(!this.service){
            this.service = ServiceBuilder.getService(this.serviceInfo.getConnectType());
            if(this.service){
                this.service.addEventListener(NetConfig.OPEN,this.onOpen,this);
                this.service.addEventListener(NetConfig.CLOSED,this.onClose,this);
                this.service.addEventListener(NetConfig.ERROR,this.onError,this);
                this.service.addEventListener(NetConfig.DATA,this.onData,this);
                this.service.connect(this.serviceInfo.getUrl(),this.serviceInfo.getPort());
            }else{
                cc.log("RemoteProxy connect service is null ")
            }

        }else{
            this.service.connect(this.serviceInfo.getUrl(),this.serviceInfo.getPort());
        }

       
    }

    reConnect(){
        if(this.service){
            cc.log(" this.connectCount ",this.connectCount);
            // if(this.connectCount < Service.MAX_SEND_NUM){
                this.service.reConnect();
                this.connectCount ++;
            // }else{
            //     this.connectCount = 0;
            //     this.clear();
            //     this.publish(NetConfig.CLOSED);
            // }                 
        }
    }

    destroy(){
        // cc.warn(" RemoteProxy destroy ");
        this.isActiveClose = true;
        if(this.service){
            if(this.service.isReady()){
                this.service.destroy();
            }
        }
        if(this.beatTimeID){
            clearInterval(this.beatTimeID);
            this.beatTimeID = 0;
        }          
    }    

    private beatTimeID:number = 0;
    sendBeat(func:Function,time:number = 3500){
        if(this.beatTimeID){
            clearInterval(this.beatTimeID);
            this.beatTimeID = 0;
        }         
        func();  
        this.beatTimeID = setInterval(()=>{
            func();
        },time);
    }   

    sendData(message:SendMessage){
        if(this.isReady()){
            let sendCount = message.getSendCount();
            if(sendCount == 0){
                this.msgHandler.encode(message,this.serviceInfo);
            }
            message.updateCount();
            // if(!this.msgMap.get(message.getProtoID())){
            this.msgMap.set(message.getProtoID(),message);
            if(message.getBlock()){
                // BlockController.instance().show();
            }            
            this.service.sendData(message);
        }else{
            cc.log(" RemoteProxy is not ready");
            this.sendFail(message);
        }
    }

    onData(bytes,protoID?:string|number){
        let message:ReceiveMessage =  this.msgHandler.decode(bytes,protoID);
        if(message){
            this.sendFinish(message);
            protoID = message.getProtoID();
            this.publish(protoID,message);
            if(message.isError()){
                this.publish(NetConfig.ERROR_DATA, message.getErrorCode());
            }
        }
    }

    onClose(data?){
        cc.log(" RemoteProxy onClose this.isActiveClose ",this.isActiveClose);
        if(this.isActiveClose){
            this.publish(NetConfig.CLOSED,data);
            this.isActiveClose = false;
            return;
        }

        this.connectTimeID = setTimeout(()=>{
            this.reConnect();
            this.clear();
        },5000)
      

    }
    onError(data?){
        this.reSendData();
    }
    clear(){
        if(this.connectTimeID){
            clearTimeout(this.connectTimeID);
            this.connectTimeID = 0;
        }        
    }
    onOpen(data?){
        cc.log("onOpen 1111111111111 ")
        this.clear();
        this.connectCount = 0;
        this.publish(NetConfig.OPEN,data)
        this.reSendData();
    }  
    addObservers(handler,array){
        for (let index = 0; index < array.length; index++) {
            let value = array[index];
                const eventName = value[0];
                let func = value[1];
                this.addEventListener(eventName,func,handler);
        }
    }
    /**
     * 
     * @param protoID 协议号
     * @param value  发送的内容
     * @param isBlock  是否显示屏蔽层
     * @param isValidate 是否需要认证，长连接无视
     * @param method  发送协议 长连接无视
     */
    sendMessage(protoID,value:Object = {},isBlock = true,isValidate = true, method = NetConfig.POST){
        let message:SendMessage = this.getMessage(protoID);
        message.setMethod(method);
        message.setBlock(isBlock);
        message.setValidate(isValidate);        
        message.setData(value);
        this.sendData(message);       
    }

    protected getMessage(protoID){
        let message = new SendMessage();
        message.setProtoID(protoID);
        return message;
    }

    reSendData():void{
    }     
   /**
     * 不论是成功还是失败 都会走这里。
     * @param message 发送结束的消息
     */
    sendFinish(message){
        let protoID = message.getProtoID();
        let rProtoID = protoID;
        let protocolMap = this.serviceInfo.getProtocalMap();
        if(protocolMap.size() > 0){
            rProtoID = protocolMap.get(protoID);
        }
        if(rProtoID){
            let msg = this.msgMap.get(rProtoID);
            if(msg){
                this.msgMap.delete(rProtoID);
                if(msg.getBlock()){
                   // BlockController.instance().close();
                }              
            }
        }
    }  

    sendFail(message:SendMessage){
        this.msgMap.set(message.getProtoID(),message);
    }       
}
